package com.example.base.utils;

import com.example.base.dto.TokenUserDTO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

/**
 * token 解析工具类
 */
@Slf4j
public class JWTUtil {

    private static final SecretKey KEY = Keys.hmacShaKeyFor("my-secret-token-to-change-in-production".getBytes(StandardCharsets.UTF_8));

    private static final Integer TOKEN_DURATION = 300;

    /**
     * 生成Token
     * @param dto
     * @return
     */
    public static String generateToken(TokenUserDTO dto){
        String sub = JacksonUtil.toJSONString(dto);
        if (StringUtils.isBlank(sub)){
            return null;
        }
        LocalDateTime now = LocalDateTime.now();
        //添加有效期
        now = now.plusSeconds(TOKEN_DURATION);
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zTime = now.atZone(zoneId);
        return Jwts.builder().claim(Claims.SUBJECT, sub).signWith(KEY).expiration(Date.from(zTime.toInstant())).compact();
    }

    /**
     * 解析token
     * @param token
     * @return
     */
    public static TokenUserDTO parseToken(String token) {
        JwtParser jwtParser = Jwts.parser()
                .verifyWith(KEY)
                .build();
        Jws<Claims> jws = jwtParser.parseSignedClaims(token);
        Claims claims = jws.getPayload();
        String sub = String.valueOf(claims.get(Claims.SUBJECT)).trim();
        return JacksonUtil.toJavaType(sub, TokenUserDTO.class);
    }

    /**
     * 判断token是否过期
     * @param token
     * @return
     */
    public static boolean isExpired(String token){
        JwtParser jwtParser = Jwts.parser().verifyWith(KEY).build();
        Jws<Claims> jws = jwtParser.parseSignedClaims(token);
        Claims claims = jws.getPayload();
        Date date = claims.getExpiration();
        Instant instant = date.toInstant();
        LocalDateTime expiredTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime now = LocalDateTime.now();
        // 当前时间 在失效时间之后  说明已经过期
        return now.isAfter(expiredTime);
    }
}
